package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/micro/go-micro"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/web"
	"github.com/micro/go-plugins/registry/consul"
	go_micro_user "go_micro_microservices/client/Interface"
	"go_micro_microservices/client/Wrappers"
)

//修饰器
type logWrapper struct { //官方提供的例子，创建自己的struct，嵌套go-micro的client 这个是自己的wrapper结构体
	client.Client
}

//传入的实例化的方法 返回对应的实例
func NewLogWrapper(c client.Client) client.Client {
	return &logWrapper{c}
}

func (this *logWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error {
	fmt.Println("执行了修饰器")                  //定义自己需要执行的中间信息 此段可相当于作为middleware
	return this.Client.Call(ctx, req, rsp) //此段代码必须执行，若不执行则会终止返回
}

func main() {
	newRegistry := consul.NewRegistry(registry.Addrs("106.12.7.53:8500"))

	engine := gin.Default() //开启gin路由

	//开启对外的http服务
	httpService := web.NewService(
		web.Address(":8002"),
		web.Name("http_client"),
		web.Registry(newRegistry),
		web.Handler(engine),
	)

	//对内的micro client
	service := micro.NewService(
		micro.Name("ClientMicro"),
		micro.Registry(newRegistry),                //真是服了 视频中没有这个能访问 go1.14版本需要添加这个 将客服端放入consul中才能找到对应的客户端
		micro.WrapClient(NewLogWrapper),            //注入修饰器 传入声明实例的名称
		micro.WrapClient(Wrappers.NewUserWrappers), //注入修饰器 里面包含熔断器
	)
	service.Init()
	userService := go_micro_user.NewUserService("micro_demo", service.Client())

	engine.Group("/")
	{
		engine.POST("/getUserList", func(ctx *gin.Context) {
			var req go_micro_user.UserRequest
			ctx.Bind(&req)
			//熔断器的使用 用来控制访问时间超时的 配置config
			//hystrixConfig := hystrix.CommandConfig{
			//	Timeout: 2000, //设置hystrix的超时时间
			//}
			//配置command
			//hystrix.ConfigureCommand("testCommand", hystrixConfig) //配置命令的名称 以及配置
			var info *go_micro_user.UserResponse //必须定义为指针 不然在熔断器中执行操作后的数据无法带出来
			var err error
			//err = hystrix.Do("testCommand", func() error { //同步执行熔断器 选择需要执行的熔断器的名称 传入需要执行的方法体 传入降级函数

			info, err = userService.GetUserInfo(context.Background(), &req)
			//return err
			//}, nil)
			if err != nil {
				ctx.JSON(200, gin.H{"err": err})
			} else {
				ctx.JSON(200, info)
			}

		})
	}

	serviceSlice, _ := newRegistry.GetService("micro_demo") //获取注册的改名称下的所有集合

	for _, v := range serviceSlice {
		fmt.Println(v)
	}

	httpService.Run()

}
